#ifndef ES_NRF24_H
#define ES_NRF24_H

#include "config.h"
#include "es_spi.h"
#include "stm_std_lib.h"




//速率功率定义 (Init成员函数使用)

#define NRF24_H_2M 0x0f
#define NRF24_H_1M 0x07
#define NRF24_H_250k 0x27

//end of 速率功率定义 (Init成员函数使用)




#define TX_ADR_WIDTH 	5  	//·¢ÉäµØÖ·¿í¶È
#define RX_ADR_WIDTH    5

#define CHANAL 40	//ÆµµÀÑ¡Ôñ 

// SPI(nRF24L01) commands ,	NRFµÄSPIÃüÁîºê¶¨Òå£¬Ïê¼ûNRF¹¦ÄÜÊ¹ÓÃÎÄµµ
#define NRF_READ_REG    0x00  // Define read command to register
#define NRF_WRITE_REG   0x20  // Define write command to register
#define RD_RX_PLOAD 0x61  // Define RX payload register address
#define WR_TX_PLOAD 0xA0  // Define TX payload register address
#define FLUSH_TX    0xE1  // Define flush TX register command
#define FLUSH_RX    0xE2  // Define flush RX register command
#define REUSE_TX_PL 0xE3  // Define reuse TX payload register command
#define NOP         0xFF  // Define No Operation, might be used to read status register

// SPI(nRF24L01) registers(addresses) £¬NRF24L01 Ïà¹Ø¼Ä´æÆ÷µØÖ·µÄºê¶¨Òå
#define CONFIG      0x00  // 'Config' register address
#define EN_AA       0x01  // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR   0x02  // 'Enabled RX addresses' register address
#define SETUP_AW    0x03  // 'Setup address width' register address
#define SETUP_RETR  0x04  // 'Setup Auto. Retrans' register address
#define RF_CH       0x05  // 'RF channel' register address
#define RF_SETUP    0x06  // 'RF setup' register address
#define STATUS      0x07  // 'Status' register address
#define OBSERVE_TX  0x08  // 'Observe TX' register address
#define CD          0x09  // 'Carrier Detect' register address
#define RX_ADDR_P0  0x0A  // 'RX address pipe0' register address
#define RX_ADDR_P1  0x0B  // 'RX address pipe1' register address
#define RX_ADDR_P2  0x0C  // 'RX address pipe2' register address
#define RX_ADDR_P3  0x0D  // 'RX address pipe3' register address
#define RX_ADDR_P4  0x0E  // 'RX address pipe4' register address
#define RX_ADDR_P5  0x0F  // 'RX address pipe5' register address
#define TX_ADDR     0x10  // 'TX address' register address
#define RX_PW_P0    0x11  // 'RX payload width, pipe0' register address
#define RX_PW_P1    0x12  // 'RX payload width, pipe1' register address
#define RX_PW_P2    0x13  // 'RX payload width, pipe2' register address
#define RX_PW_P3    0x14  // 'RX payload width, pipe3' register address
#define RX_PW_P4    0x15  // 'RX payload width, pipe4' register address
#define RX_PW_P5    0x16  // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17  // 'FIFO Status Register' register address
#define RX_EMPTY	0x01  //  RX FIFO empty flag.	1: RX FIFO empty.	0: Data in RX FIFO.


#define MAX_RT      0x10 //´ïµ½×î´óÖØ·¢´ÎÊýÖÐ¶Ï±êÖ¾Î»
#define TX_DS		0x20 //·¢ËÍÍê³ÉÖÐ¶Ï±êÖ¾Î»	  // 

#define RX_DR		0x40 //½ÓÊÕµ½Êý¾ÝÖÐ¶Ï±êÖ¾Î»


#define NRF_CSN_HIGH()      GPIO_SetBits(GPIOA, GPIO_Pin_4)
#define NRF_CSN_LOW()       GPIO_ResetBits(GPIOA, GPIO_Pin_4)		        //csnÖÃµÍ
#define NRF_CE_HIGH()	      GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define NRF_CE_LOW()	      GPIO_ResetBits(GPIOA,GPIO_Pin_1)			      //CEÖÃµÍ
#define NRF_Read_IRQ()		  GPIO_ReadInputDataBit ( GPIOA, GPIO_Pin_0)  //ÖÐ¶ÏÒý½Å

#define R_RX_PL_WID 0x60
#define FEATURE 0x1D
#define DYNPD 0x1C


#ifndef NRF24_MODE
//兼容旧项目，2.4默认Plane_Mode
#define NRF24_MODE Plane_Mode
#endif

typedef enum { Smart_Mode = 0, Plane_Mode } NRF24Mode;



//CE => A1
//CSN => A4
class es_nrf24
{
public:

	u8 wait_for_ACK;
	NRF24Mode commMode;
	bool transmitMode;

	inline void bind(u8* addr)
	{
		for (int i = 0; i < 5; i++)
		{
			rx_addr[i] = addr[i];
		}
	}

  /*
	* power_speed：功率速率，见顶部define
	*/
	inline void init(CSPI* s,u8 power_speed)
	{
		this->pow_speed=power_speed;
		
		spi = s;
		init_rcc();
		init_gpio();
		
		//rx_payload_len = 4;
		
		IRQ_config();
		
		wait_for_ACK = false;
		

			rx_mode();
		
	}
	inline u8 NRF_Check(void)
	{
		u8 buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
		u8 buf1[5];
		u8 i; 
		
		//write and then read, check for the same data
		writeBuffer(NRF_WRITE_REG+TX_ADDR, buf, 5);

		readBuffer(TX_ADDR, buf1, 5); 

          
		for(i=0;i<5;i++)
		{
			if(buf1[i]!=0xC2)
			break;
		} 
    
		if(i==5)
			return 1 ;        //nrf-spi works
		else
			return 0 ;        //not working
	}
	
	
	
	
	u8 txData(u8* addr, u8* txBuffer, u8 len)
	{
		//如果正在等ack， 退出， 丢掉当前发送包，返回错误
		//if(wait_for_ACK) return 1;
		
		//set address0
		for(int i=0; i<5 ;i++)
		{
			tx_addr[i] = addr[i];
			rx_addr[i] = addr[i];
		}
		if(!transmitMode)
			tx_mode();
		return tx(txBuffer, len);
	}
	

	
	
	inline u8 rxData(u8* addr, u8* rxBuffer, u8 &len)
	{
//		rx_payload_len = len;
		//set address
		for(int i=0; i<5 ;i++)
		{
			rx_addr[i] = addr[i];
		}
		if(transmitMode)
			rx_mode();
		return rx(rxBuffer, len);
	}
	
	
	
	
	
	u8 readStat()
	{
		u8 stat;
                           
 		stat = readReg(STATUS);	

		return stat;
	}
	inline void flushTx()
	{
		writeReg(NRF_WRITE_REG+STATUS,readStat());
		
		writeReg(FLUSH_TX,NOP);
		
		
	}
	inline void flushRx()
	{
		writeReg(FLUSH_RX,NOP);
	}
	
	
	
	
	inline void rx_mode()
	{
		NRF_CE_LOW();
		//spi.WriteReg()
		writeBuffer(NRF_WRITE_REG+RX_ADDR_P0,rx_addr,RX_ADR_WIDTH);//Ð´RX½ÚµãµØÖ·

		if (commMode == Smart_Mode) {
			writeReg(NRF_WRITE_REG + EN_AA, 0x01);    //开启 autoack
		}
		else if (commMode == Plane_Mode) {
			writeReg(NRF_WRITE_REG + EN_AA, 0x00);   //关闭 autoack
		}
		writeReg(NRF_WRITE_REG+EN_RXADDR,0x01);//Ê¹ÄÜÍ¨µÀ0µÄ½ÓÊÕµØÖ·    

		writeReg(NRF_WRITE_REG+RF_CH,CHANAL);      //ÉèÖÃRFÍ¨ÐÅÆµÂÊ    

		writeReg(NRF_WRITE_REG+RX_PW_P0,3);//Ñ¡ÔñÍ¨µÀ0µÄÓÐÐ§Êý¾Ý¿í¶È      

		writeReg(NRF_WRITE_REG+RF_SETUP,pow_speed); //速率功率

		writeReg(NRF_WRITE_REG+CONFIG, 0x0f);  //ÅäÖÃ»ù±¾¹¤×÷Ä£Ê½µÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,½ÓÊÕÄ£Ê½ 

		//enable ack payload and dynamic payload
		writeReg(NRF_WRITE_REG+FEATURE, 0x06);
		
		//enable dynamic payload length
		writeReg(NRF_WRITE_REG+DYNPD, 0x01);
		
		NRF_CE_HIGH();
		
		transmitMode = false;
	}
	inline void rx_mode_mod()
	{
		NRF_CE_LOW();
		//spi.WriteReg()
//		writeBuffer(NRF_WRITE_REG+RX_ADDR_P0,rx_addr,RX_ADR_WIDTH);//Ð´RX½ÚµãµØÖ·

//		writeReg(NRF_WRITE_REG+EN_AA,0x01);    //Ê¹ÄÜÍ¨µÀ0µÄ×Ô¶¯Ó¦´ð    

//		writeReg(NRF_WRITE_REG+EN_RXADDR,0x01);//Ê¹ÄÜÍ¨µÀ0µÄ½ÓÊÕµØÖ·    

//		writeReg(NRF_WRITE_REG+RF_CH,CHANAL);      //ÉèÖÃRFÍ¨ÐÅÆµÂÊ    

//		writeReg(NRF_WRITE_REG+RX_PW_P0,3);//Ñ¡ÔñÍ¨µÀ0µÄÓÐÐ§Êý¾Ý¿í¶È      

//		writeReg(NRF_WRITE_REG+RF_SETUP,pow_speed); //速率功率

//		writeReg(NRF_WRITE_REG+CONFIG, 0x0f);  //ÅäÖÃ»ù±¾¹¤×÷Ä£Ê½µÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,½ÓÊÕÄ£Ê½ 

//		//enable ack payload and dynamic payload
//		writeReg(NRF_WRITE_REG+FEATURE, 0x06);
//		
//		//enable dynamic payload length
//		writeReg(NRF_WRITE_REG+DYNPD, 0x01);
		
		
		NRF_CE_HIGH();
	}
	
	
//private:
	u8 tx_addr[5];
	u8 rx_addr[5];
	//u8 rx_payload_len;
	CSPI* spi;

	u8 pow_speed;
		
	inline void IRQ_config()
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
		
		NVIC_InitTypeDef nvicInit;
	
			

		//中断抢占优先级组别选择
//		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);

		nvicInit.NVIC_IRQChannel=EXTI0_IRQn;		//ÖÐ¶Ïchannel £¬PB0Ê¹ÓÃÍâ²¿ÖÐ¶ÏÏß0(²Î¿¼stm32ÎÄµµ)
		nvicInit.NVIC_IRQChannelPreemptionPriority=1;			//ÇÀÕ¼ÓÅÏÈ¼¶
		nvicInit.NVIC_IRQChannelSubPriority=1;		//响应优先级1
		nvicInit.NVIC_IRQChannelCmd=ENABLE;		//¿ªÆô
		NVIC_Init(&nvicInit);

		
		EXTI_InitTypeDef extiInit;
	
		//Íâ²¿ÖÐ¶ÏÏßÅäÖÃ,PB0Ê¹ÓÃLine0
		GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
		
		extiInit.EXTI_Line=EXTI_Line0;		//PB0Ê¹ÓÃÍâ²¿ÖÐ¶ÏÏß0(²Î¿¼stm32ÎÄµµ)
		extiInit.EXTI_Mode=EXTI_Mode_Interrupt;		//ÖÐ¶ÏÄ£Ê½
		extiInit.EXTI_Trigger=EXTI_Trigger_Falling;		//ÏÂ½µÑØÄ£Ê½
		extiInit.EXTI_LineCmd=ENABLE;		//Æô¶¯
		
		EXTI_Init(&extiInit);
	}



	inline u8 rx(u8* buff, u8& len)
	{
//		u8 stat;
//		
//  	//NRF_CE_HIGH();
//		//wait for IRQ
//		//while(NRF_Read_IRQ()!=0); 
//		
		NRF_CE_LOW();  
//		
		////read status reg
		//stat=readReg(STATUS);

		////clear IRQ
		//writeReg(NRF_WRITE_REG+STATUS,stat);

		//read data len
		len = readReg(R_RX_PL_WID);
//		
//		//data received 
		//if(stat&RX_DR)
		//{
		readBuffer(RD_RX_PLOAD, buff, len);

			//writeReg(FLUSH_RX, NOP);
//			
		//	return RX_DR;
		//} // nodata
		return 0;
	}



	inline u8 tx(u8* buff, u8 len)
	{
		/*ceÎªµÍ£¬½øÈë´ý»úÄ£Ê½1*/
		NRF_CE_LOW();

		/*Ð´Êý¾Ýµ½TX BUF ×î´ó 32¸ö×Ö½Ú*/						
		writeBuffer(WR_TX_PLOAD,buff,len);

		//chip enable set to HIGH
		NRF_CE_HIGH();
			
		//lock irq
		if(commMode == Smart_Mode)
			return (true);
		return true;
	}
	


	inline void tx_mode()
	{
//		int i;
		NRF_CE_LOW();		

		writeBuffer(NRF_WRITE_REG+TX_ADDR,tx_addr,TX_ADR_WIDTH);    //Ð´TX½ÚµãµØÖ· 

		writeBuffer(NRF_WRITE_REG+RX_ADDR_P0,rx_addr,RX_ADR_WIDTH); //ÉèÖÃTX½ÚµãµØÖ·,Ö÷ÒªÎªÁËÊ¹ÄÜACK   


		if(commMode == Smart_Mode)
		{
			writeReg(NRF_WRITE_REG + EN_AA, 0x01);    //auto ack
			writeReg(NRF_WRITE_REG + SETUP_RETR, 0x1a); //重发10次， 间隔500us
			
		}
		else if(commMode == Plane_Mode)
		{
			writeReg(NRF_WRITE_REG + EN_AA, 0x00);    //auto ack
			writeReg(NRF_WRITE_REG + SETUP_RETR, 0x10); //重发10次， 间隔500us
		}
   

		writeReg(NRF_WRITE_REG+EN_RXADDR,0x01); //Ê¹ÄÜÍ¨µÀ0µÄ½ÓÊÕµØÖ·  


		writeReg(NRF_WRITE_REG+RF_CH,CHANAL);       //ÉèÖÃRFÍ¨µÀÎªCHANAL

		writeReg(NRF_WRITE_REG+RF_SETUP,pow_speed);  //速率功率

		writeReg(NRF_WRITE_REG+CONFIG,0x0e);    //ÅäÖÃ»ù±¾¹¤×÷Ä£Ê½µÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,·¢ÉäÄ£Ê½,¿ªÆôËùÓÐÖÐ¶Ï

		/*CEÀ­¸ß£¬½øÈë·¢ËÍÄ£Ê½*/	
		NRF_CE_HIGH();
		
		//for( i=0;i<10000;i++);
		
		transmitMode = true;
	}

	inline u8 readReg(u8 reg)
	{
		u8 result;
		
		//set nrf pins to enable chip and communication 
		NRF_CE_LOW();
		NRF_CSN_LOW();
		
		//read
		result = spi->ReadReg(reg);
		
		//disable communication 
		NRF_CSN_HIGH();
		NRF_CE_HIGH();
		return result;
	}
	inline u8 writeReg(u8 reg, u8 data)
	{
		u8 stat;
		
		NRF_CE_LOW();
		NRF_CSN_LOW();
		
		stat = spi->WriteReg(reg, data);
		
		NRF_CSN_HIGH();
		NRF_CE_HIGH();
		return stat;
	}
	
	inline u8 writeBuffer(u8 reg, u8* buf, u8 len)
	{
		u8 stat;
		//enable chip
		NRF_CE_LOW();
		//enable spi communication 
		NRF_CSN_LOW();
		//write from spi bus
		stat = spi->WriteBuf(reg, buf, len);
		//disable spi
		NRF_CSN_HIGH();
		NRF_CE_HIGH();
		return stat;
	}
	
	inline u8 readBuffer(u8 reg, u8* buf, u8 len)
	{
		u8 stat;
		//enable chip
		NRF_CE_LOW();
		//enable spi communication 
		NRF_CSN_LOW();
		//read from spi bus
		stat = spi->ReadBuf(reg, buf, len);
		//disable spi
		NRF_CSN_HIGH();
		
		NRF_CE_HIGH();
		return stat;
	}
	
	
	
	inline void init_rcc()
	{
		 /*������ӦIO�˿ڵ�ʱ��*/
		 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
		
	}
	inline void init_gpio()
	{
		GPIO_InitTypeDef GPIO_InitStructure;
		 /*���� SPI_NRF_SPI�� SCK,MISO(IPU?),MOSI���ţ�GPIOA^5,GPIOA^6,GPIOA^7 */
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //���ù���
		GPIO_Init(GPIOA, &GPIO_InitStructure);  

		/*����SPI_NRF_SPI��CE����,��SPI_NRF_SPI�� CSN ����*/
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_4;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_Init(GPIOA, &GPIO_InitStructure);
		
		 /*����SPI_NRF_SPI��IRQ����*/
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;  //��������
		GPIO_Init(GPIOA, &GPIO_InitStructure); 
		
		NRF_CSN_HIGH();
		
	}
	
};

#endif
